/* This file is part of MyRename
 * Copyright (C) 2005-2009 Kai-Chieh Ku (kjackie@gmail.com)
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either
 * version 3 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

// FileWnd.cpp : implementation file
//

#include "stdafx.h"
#include "MyRename.h"
#include "MyRenameDlg.h"
#include "resource.h"
#include "language.h"
#include "preferences.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#define LSPLPOS	 GetSplitterPos(true, false)
#define RSPLPOS	 GetSplitterPos(false, false)
#define LSPLPOSP GetSplitterPos()
#define RSPLPOSP GetSplitterPos(false)
#define DIST 100

// CFileWnd dialog

IMPLEMENT_DYNAMIC(CFileWnd, CDialog)
CFileWnd::CFileWnd(CWnd* pParent /*=NULL*/)
	: CResizableDialog(CFileWnd::IDD, pParent), m_bLockUpdate(false), m_uTimer(0)
{
}

CFileWnd::~CFileWnd()
{
}

void CFileWnd::DoDataExchange(CDataExchange* pDX)
{
	CResizableDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CFileWnd)
	DDX_Control(pDX, IDC_DIR_TREE, m_DirTree);
	DDX_Control(pDX, IDC_FILE_LIST1, m_PreList);
	DDX_Control(pDX, IDC_FILE_LIST2, m_PostList);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CFileWnd, CResizableDialog)
	//{{AFX_MSG_MAP(CFileWnd)
	ON_WM_TIMER()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

BOOL CFileWnd::OnInitDialog()
{
	CResizableDialog::OnInitDialog();

	m_DirTree.Init();
	m_PreList.Init();
	m_PostList.Init();
	
	//set these pointer to synchronize scroll bars
	m_PreList.m_pFriendList = &m_PostList;
	m_PostList.m_pFriendList = &m_PreList;

	{
		CRect rc(0, 0, 5, 10), //initialize w/ this value to make sure thay are vertical spiltters
			rcParent;
		CWnd *pWnd;
		// construct splitters --->
#define CREATE_SPL(id, obj) {\
		pWnd = GetDlgItem(id);\
		if (pWnd) pWnd->DestroyWindow();\
		obj.Create(WS_CHILD | WS_VISIBLE, rc, this, id);\
}

		CREATE_SPL(IDC_SPLITTER_L, m_leftSplitter);
		CREATE_SPL(IDC_SPLITTER_R, m_rightSplitter);

#undef CREATE_SPL
		// construct splitters <---

		// place controls --->
		GetWindowRect(rcParent);

		const int iLpos = rcParent.Width() * thePrefs.uLSpiltterPos / 100, iRpos = rcParent.Width() * thePrefs.uRSpiltterPos / 100;

		m_DirTree.GetWindowRect(rc);
		ScreenToClient(rc);
		rc.right = iLpos;
		m_DirTree.MoveWindow(rc);

		m_PreList.GetWindowRect(rc);
		ScreenToClient(rc);
		rc.left = iLpos + 5;
		rc.right = iRpos;
		m_PreList.MoveWindow(rc);

		m_PostList.GetWindowRect(rc);
		ScreenToClient(rc);
		rc.left = iRpos + 5;
		m_PostList.MoveWindow(rc);
		// place controls <---

		// place texts --->
#define MOVE_TEXT(id, pos) {\
		pWnd = GetDlgItem(id);\
		pWnd->GetWindowRect(rc);\
		ScreenToClient(rc);\
		rc.MoveToX(pos + 5);\
		pWnd->MoveWindow(rc);\
}

		MOVE_TEXT(IDC_TX_EFN, iLpos);
		MOVE_TEXT(IDC_TX_PFN, iRpos);

#undef MOVE_TEXT
		// place texts <---

		UpdateSplitter();
	}
	
	UpdateAnchors(true);
	UpdateSplitterRange();

	ArrangeLayout();

	return TRUE;
}

void CFileWnd::Localize()
{
	SetDlgItemText(IDC_TX_DIR, GetResString(IDS_LB_DIR));
	SetDlgItemText(IDC_TX_EFN, GetResString(IDS_LB_EFN));
	SetDlgItemText(IDC_TX_PFN, GetResString(IDS_LB_PFN));

	m_DirTree.Localize();
	m_PreList.Localize();
	m_PostList.Localize();
}

int CFileWnd::GetSplitterPos(bool left /* = true */, bool percent /* = true */)
{
	CRect rc;
	int pos = left ? m_leftSplitter.getPos() : m_rightSplitter.getPos();

	GetClientRect(rc);

	return percent ? (pos - rc.left) * 100 / rc.Width() : pos;
}

LRESULT CFileWnd::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam) 
{
	switch (message) {
		case WM_NOTIFY:
			if (wParam == IDC_SPLITTER_L || wParam == IDC_SPLITTER_R) {	
				SPC_NMHDR* pHdr = (SPC_NMHDR*) lParam;
				DoResize(pHdr->delta, (UINT) wParam);
			}
			break;
		case WM_WINDOWPOSCHANGED:
			{
				CRect rcW;
				GetClientRect(rcW);

				if (m_rightSplitter && m_leftSplitter && rcW.Height() > 0) Invalidate();
			}
			break;
		case WM_PAINT:
		case WM_SIZE:
			UpdateSplitter();
			ArrangeLayout();
			break;
	}

	return CResizableDialog::DefWindowProc(message, wParam, lParam);
}

void CFileWnd::UpdateSplitter()
{
	if (m_rightSplitter && m_leftSplitter) {
		CRect rc, rcspl, rcctl;
		GetClientRect(rc);
		if (rc.Height() > 0) {
			m_DirTree.GetWindowRect(rcctl);
			ScreenToClient(rcctl);
			rcspl.left = rcctl.right;
			rcspl.right = rcspl.left + 5;
			rcspl.top = rcctl.top;
			rcspl.bottom = rcctl.bottom;
			m_leftSplitter.MoveWindow(rcspl);
			m_PreList.GetWindowRect(rcctl);
			ScreenToClient(rcctl);
			rcspl.left = rcctl.right;
			rcspl.right = rcspl.left + 5;
			m_rightSplitter.MoveWindow(rcspl);
			UpdateSplitterRange();
		}
	}
}

void CFileWnd::UpdateSplitterRange()
{
	CRect rcctl;
	m_DirTree.GetWindowRect(rcctl);
	ScreenToClient(rcctl);
	m_leftSplitter.SetRange(rcctl.left + DIST, RSPLPOS - DIST);
	m_PostList.GetWindowRect(rcctl);
	ScreenToClient(rcctl);
	m_rightSplitter.SetRange(LSPLPOS + DIST, rcctl.right - DIST);
}

void CFileWnd::DoResize(int delta, UINT nID)
{
	CRect rc;
	GetClientRect(rc);

	switch (nID) {
		case IDC_SPLITTER_L:
			CSplitterControl::ChangeWidth(&m_DirTree, delta);
			CSplitterControl::ChangeWidth(&m_PreList, -delta, CW_RIGHTALIGN);
			CSplitterControl::ChangePos(GetDlgItem(IDC_TX_EFN), -delta, 0);
			break;
		case IDC_SPLITTER_R:
			CSplitterControl::ChangeWidth(&m_PreList, delta);
			CSplitterControl::ChangeWidth(&m_PostList, -delta, CW_RIGHTALIGN);
			CSplitterControl::ChangePos(GetDlgItem(IDC_TX_PFN), -delta, 0);
			break;
	}

	UpdateAnchors();
	UpdateSplitterRange();
	Invalidate();
	UpdateWindow();
	thePrefs.uLSpiltterPos = LSPLPOSP;
	thePrefs.uRSpiltterPos = RSPLPOSP;
}

void CFileWnd::UpdateAnchors(bool bRemoveFirst /* = false */) {

	if (!bRemoveFirst)
		RemoveAllAnchors();

	AddAnchor(IDC_TX_DIR, TOP_LEFT, TOP_LEFT);
	AddAnchor(IDC_TX_EFN, CSize(LSPLPOSP, 0), CSize(RSPLPOSP, 0));
	AddAnchor(IDC_TX_PFN, CSize(RSPLPOSP, 0), TOP_RIGHT);
	AddAnchor(IDC_DIR_TREE, TOP_LEFT, CSize(LSPLPOSP, 100));
	AddAnchor(IDC_FILE_LIST1, CSize(LSPLPOSP, 0), CSize(RSPLPOSP, 100));
	AddAnchor(IDC_FILE_LIST2, CSize(RSPLPOSP, 0), BOTTOM_RIGHT);
}

void CFileWnd::LockUpdate(UINT uTime/* = 0*/)
{
	if (uTime) {
		KillTimer(FT_LOCK);
		SetTimer(FT_LOCK, uTime, NULL);
	}
	m_bLockUpdate = true;
}

void CFileWnd::UnlockUpdate()
{
	if (thePrefs.all_ready) m_bLockUpdate = false;
}

void CFileWnd::UpdateList(bool update_left /* = false */, const CFileName *mask /* = NULL */)
{
	if (!m_bLockUpdate) {
		CTRPANWND->ConvStart(); //initialize the string conversion (and update variables)
		if (update_left) {
			if (thePrefs.bAutoDelThumbs)
				DeleteFile(thePrefs.sLastPath + _T("Thumbs.db")); //delete system thumb files
			m_PreList.CreateList(thePrefs.sLastPath, mask);
		}
		m_PostList.CreateList(m_PreList, CControlPanel::strchange);
		if (!update_left) m_PreList.Synchronize();
	}
}

// CFileWnd message handlers

void CFileWnd::OnTimer(UINT nIDEvent)
{
	switch (nIDEvent) {
		case FT_LOCK:
			KillTimer(FT_LOCK);
			UnlockUpdate();
			return;
		case FT_UPDATE:
			KillTimer(FT_UPDATE);
			UpdateList(true, &thePrefs.fnMask);
		case FT_UPDATER:
			KillTimer(FT_UPDATER);
			UpdateList();
			return;
	}

	CResizableDialog::OnTimer(nIDEvent);
}
